from PyQt6.QtWidgets import *
from PyQt6.QtGui import *
from PyQt6.QtCore import *

from AikPS_custom.childWindow import *
import sys
import cv2
import numpy as np
import matplotlib.pyplot as plt
import pyttsx3

#启动界面
class MySplash(QSplashScreen):
    def __init__(self,pathToGIF):
        self.movie = QMovie(pathToGIF)
        self.movie.jumpToFrame(0)
        pixmap = QPixmap(self.movie.frameRect().size())
        QSplashScreen.__init__(self,pixmap)
        self.movie.frameChanged.connect(self.repaint)

    def showEvent(self, event):
        self.movie.start()

    def hideEvent(self, event):
        self.movie.stop()

    def paintEvent(self,event):
        painter = QPainter(self)
        pixmap = self.movie.currentPixmap()
        self.setMask(pixmap.mask())
        painter.drawPixmap(0,0,pixmap)
    

class Window(QMainWindow):
    def __init__(self):
        super().__init__()

        self.file_opened = 0
        self.setWindowTitle("AikPS")
        self.setWindowIcon(QIcon("AikPS_custom\\UI_image\\UI.png"))

        #可以以原图大小打开，setFixedSize为设定恒定的尺寸
        self.resize(980,980)

        #背景图片
        #背景图片路径得用//否则无法读取
        self.setStyleSheet("""
        QMainWindow{
            background-image:url("AikPS_custom//UI_image//ikun.jpg");
            background-repeat:repeat;
            background-position:center;
        }""")
        #撤销字典
        self.revocation_dict = {}
        #子窗口撤销列表
        self.child_window_list = [0]
        #撤销键值
        self.revocation_index = 0

        #图像显示
        self.label = QLabel()
        self.setCentralWidget(self.label)

        #初始化子窗口，避免关闭子窗口时出错
        self.fliter_child_window = FilterChild()
        self.morph_child_window = MorphChild()
        self.grad_child_window = GradChild()
        self.threshold_child_window = ThresholdChild()
        self.edge_child_window = EdgeChild()
        self.contour_child_window = ContourChild()
        self.equalize_child_window = EqualizeChild()
        self.houghLine_child_window = HoughLineChild()
        self.light_child_window = LightChild()
        self.gamma_child_window = GammaChild()

        self.createMenuBar()
        self.creatMainAction()
        self.ImgFuncListWidget()

    '''菜单部分'''
    #创建菜单栏
    def createMenuBar(self):
        menuBar = self.menuBar()
        self.setMenuBar(menuBar)

        self.fileMenu = menuBar.addMenu("文件(F)")
    #创建主选项
    def creatMainAction(self):
        #文件菜单
        self.open_file_action = QAction(QIcon("AikPS_custom\\UI_image\\openfile_icon.png"),"打开(O)...",self)
        self.open_file_action.setShortcut("Ctrl+N")
        self.fileMenu.addAction(self.open_file_action)
        self.open_file_action.triggered.connect(self.readFile)
        
        self.save_file_action = QAction(QIcon("AikPS_custom\\UI_image\\savefile_icon.png"),"保存(S)...",self)
        self.save_file_action.setShortcut("Ctrl+S")
        self.fileMenu.addAction(self.save_file_action)
        self.save_file_action.triggered.connect(self.saveFile)


        self.back_up = QAction(QIcon("AikPS_custom\\UI_image\\backup_icon.png"),"还原",self)
        self.back_up.setShortcut("Ctrl+O")
        self.fileMenu.addAction(self.back_up)
        self.back_up.triggered.connect(self.BackUp)

        self.revocation = QAction(QIcon("AikPS_custom\\UI_image\\revocation_icon.png"),"撤销(Z)",self)
        self.revocation.setShortcut("Ctrl+Z")
        self.fileMenu.addAction(self.revocation)
        self.revocation.triggered.connect(self.Revocation)

        self.fileMenu.addSeparator()
        self.ExitAction = QAction(QIcon("AikPS_custom\\UI_image\\exit_icon.png"),"退出(X)...",self)
        self.ExitAction.setShortcut("Ctrl+X")
        self.ExitAction.triggered.connect(self.close)
        self.fileMenu.addAction(self.ExitAction)

    #视图 -> 工具栏
    def ImgFuncListWidget(self):
        self.func_dock_widget = QDockWidget()
        self.func_dock_widget.setTitleBarWidget(QLabel("图像操作"))
        self.func_dock_widget.setFont(QFont("STXinwei",14))

        self.list_widget = QListWidget()
        self.list_widget.setFixedHeight(64)
        #列表从左到右排列
        self.list_widget.setFlow(QListView.Flow.LeftToRight)
        self.list_widget.setViewMode(QListView.ViewMode.IconMode)
        #列表不可拖动
        self.list_widget.setAcceptDrops(False)

        '''设置列表内容'''
        self.gray_list_item = QListWidgetItem("灰度图")
        self.gray_list_item.setIcon(QIcon("AikPS_custom\\UI_image\\gray_icon.png"))
        self.list_widget.addItem(self.gray_list_item)

        self.filter_list_item = QListWidgetItem("平滑处理")
        self.filter_list_item.setIcon(QIcon("AikPS_custom\\UI_image\\filter_icon.png"))
        self.list_widget.addItem(self.filter_list_item)

        self.equalize_list_item = QListWidgetItem("均衡化")
        self.equalize_list_item.setIcon(QIcon("AikPS_custom\\UI_image\\equalize_icon.png"))
        self.list_widget.addItem(self.equalize_list_item)

        self.morph_list_item = QListWidgetItem("形态学")
        self.morph_list_item.setIcon(QIcon("AikPS_custom\\UI_image\\morph_icon.png"))
        self.list_widget.addItem(self.morph_list_item)

        self.grad_list_item = QListWidgetItem("图像梯度")
        self.grad_list_item.setIcon(QIcon("AikPS_custom\\UI_image\\grad_icon.png"))
        self.list_widget.addItem(self.grad_list_item)

        self.threshold_list_item = QListWidgetItem("阈值处理")
        self.threshold_list_item.setIcon(QIcon("AikPS_custom\\UI_image\\threshold_icon.png"))
        self.list_widget.addItem(self.threshold_list_item)

        self.edge_list_item = QListWidgetItem("边缘检测")
        self.edge_list_item.setIcon(QIcon("AikPS_custom\\UI_image\\edge_icon.png"))
        self.list_widget.addItem(self.edge_list_item)

        self.contour_list_item = QListWidgetItem("轮廓检测")
        self.contour_list_item.setIcon(QIcon("AikPS_custom\\UI_image\\contour_icon.png"))
        self.list_widget.addItem(self.contour_list_item)

        self.houghLine_list_item = QListWidgetItem("直线检测")
        self.houghLine_list_item.setIcon(QIcon("AikPS_custom\\UI_image\\houghLine_icon.png"))
        self.list_widget.addItem(self.houghLine_list_item)

        self.light_list_item = QListWidgetItem("亮度调节")
        self.light_list_item.setIcon(QIcon("AikPS_custom\\UI_image\\light_icon.png"))
        self.list_widget.addItem(self.light_list_item)

        self.gamma_list_item = QListWidgetItem("伽马校正")
        self.gamma_list_item.setIcon(QIcon("AikPS_custom\\UI_image\\gamma_icon.png"))
        self.list_widget.addItem(self.gamma_list_item)
        
        self.histogram_item = QListWidgetItem("直方图")
        self.histogram_item.setIcon(QIcon("AikPS_custom\\UI_image\\histogram_icon.png"))
        self.list_widget.addItem(self.histogram_item)

        self.list_widget.itemClicked.connect(self.itemIsClick)
        '''放置悬浮窗'''
        self.func_dock_widget.setFeatures(QDockWidget.DockWidgetFeature.NoDockWidgetFeatures)
        self.func_dock_widget.setWidget(self.list_widget)
        self.addDockWidget(Qt.DockWidgetArea.TopDockWidgetArea,self.func_dock_widget)

    def show_img(self,img):
        #cv 转 qt
        #参数:数据源，宽，高，行字节数（无则将会退出程序）
        qImg = QImage(img,img.shape[1],img.shape[0],img.shape[1] * 3,QImage.Format.Format_RGB888).rgbSwapped()
        #将QImage转为QPixmap
        pixImg = QPixmap.fromImage(qImg)
        self.label.setPixmap(pixImg)
        self.label.setScaledContents(True)

    '''文件处理部分'''
    #读取文件
    def readFile(self):
        pyttsx3.speak("打开文件")
        #返回文件路径和文件类型
        self.fname,_ = QFileDialog.getOpenFileName(
                self,
                "打开文件",
                "",
                "Img File(*.jpg *.png *.bmp)",
                )
        if self.fname == '':
            pass
        else:
            self.file_opened = 1
            #在图像处理函数中：给 self.process_img 提供初始图像 在保存文件函数中：作为保存的文件
            self.img = cv2.imread(self.fname)
            #在图像处理函数中：用于保存 在一次使用 同一图像处理类型(如形态学) 的 不同模式(如腐蚀，膨胀) 对于 self.img 的结果
            # self.img 在 执行一个处理类型 的过程中不会更改，更改的是self.process_img
            #在保存文件函数中：用于更新 self.img
            self.process_img = self.img.copy()
            self.show_img(self.img)
            
    #保存文件
    def saveFile(self):
        if not self.file_opened:
            QMessageBox.information(self,"未打开文件","暂未打开文件！")
        else:
            pyttsx3.speak("保存文件")
            save_file_name,_ = QFileDialog.getSaveFileName(
                self,
                "保存文件",
                "",
                "JPG (*.jpg);;PNG (*.png);;BMP (*.bmp)",
            )
            if save_file_name == '':
                pass
            else:
                pyttsx3.speak("保存成功")
                #尝试保存，遇到相同文件名时会询问是否覆盖
                self.img = self.process_img
                cv2.imwrite(save_file_name,self.img)

    #撤销字典赋值
    def dictAssign(self):
        #self.tmp 用于保存对图像进行操作之前的初始图像
        img_copy = self.tmp.copy()
        #值为 存储图像的数组
        self.revocation_dict[self.revocation_index] = img_copy
        self.revocation_index += 1
  
    #撤销
    def Revocation(self):
        pyttsx3.speak("撤销")
        try:
            #让 self.img 访问 之前的图像
            self.img = self.revocation_dict[self.revocation_index - 1]
            self.RevocationCloseChildWindow()
            self.revocation_index -= 1
            #process_img 和 img 同步 防止 process_img 仍为之前进行操作的图像
            self.process_img = self.img
            self.show_img(self.img)
            if self.revocation_index == 0:
                self.closeAllChildWindow()
            pyttsx3.speak("撤销成功")
        except:
            pyttsx3.speak("撤销失败")
            QMessageBox.information(self,"出错啦！","未打开文件或已处于初始状态！")

    #还原
    def BackUp(self):
        reply = QMessageBox.warning(self,"警告！","还原将会重置图像并且无法撤销，是否继续？",QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No)
        if reply:
            pyttsx3.speak("还原")
            try:
                #访问撤销字典里的初始图片
                self.img = self.revocation_dict[0]
                self.process_img = self.img
                #撤销字典初始化
                self.revocation_index = 0
                self.revocation_dict.clear()
                #子窗口列表初始化
                self.child_window_list = [0]
                self.closeAllChildWindow()
                self.show_img(self.img)
                pyttsx3.speak("还原成功")
            except:
                pyttsx3.speak("还原失败")
                QMessageBox.information(self,"错误！","未打开图像文件或已处于初始状态！")
    
    #点击图像处理组件
    def itemIsClick(self):
        if not self.file_opened:
            QMessageBox.information(self,"出错啦！","未打开图像文件")
        else:
            item = self.list_widget.currentItem()
            if item.text() == "灰度图":
                #更新图片
                self.img = self.process_img
                #保存操作之前的图片
                self.tmp = self.img
                self.dictAssign()
                pyttsx3.speak("图像灰度化")
                try:
                    img_gray = cv2.cvtColor(self.img,cv2.COLOR_RGB2GRAY)
                    # self.RevocationCloseChildWindow()
                    self.child_window_list.append('gray')
                    self.process_img = cv2.cvtColor(img_gray,cv2.COLOR_GRAY2BGR)
                    self.show_img(self.process_img)
                except:
                    pass
            elif item.text() == "平滑处理":
                #更新图片
                self.img = self.process_img
                #保存操作之前的图片
                self.tmp = self.img
                self.dictAssign()
                pyttsx3.speak("平滑处理")
                try:
                    self.fliter_child_window.show()
                    self.child_window_list.append('fliter')
                    if self.fliter_child_window.isVisible():
                        self.FilterFuncandAttr()
                        self.fliter_child_window.fliter_kind_combox.currentIndexChanged.connect(self.FilterFuncandAttr)
                        self.fliter_child_window.fliter_ksize_spinbox.valueChanged.connect(self.FilterFuncandAttr)
                except:
                    pass
            elif item.text() == "形态学":
                #更新图片
                self.img = self.process_img
                #保存操作之前的图片
                self.tmp = self.img
                self.dictAssign()
                pyttsx3.speak("形态学")
                try:
                    self.morph_child_window.show()
                    self.child_window_list.append('morph')
                    if self.morph_child_window.isVisible():
                        #默认为腐蚀操作，直接操作就行
                        self.MorphFuncandAttr()
                        self.morph_child_window.morph_kind_combox.currentIndexChanged.connect(self.MorphFuncandAttr)
                        self.morph_child_window.morph_kshape_combox.currentIndexChanged.connect(self.MorphFuncandAttr)
                        self.morph_child_window.morph_ksize_spinbox.valueChanged.connect(self.MorphFuncandAttr)
                except:
                    pass
            elif item.text() == "图像梯度":
                #更新图片
                self.img = self.process_img
                #保存操作之前的图片
                self.tmp = self.img
                self.dictAssign()
                pyttsx3.speak("图像梯度")
                try:
                    self.grad_child_window.show()
                    self.child_window_list.append('grad')
                    if self.grad_child_window.isVisible():
                        self.GradFuncandAttr()
                        self.grad_child_window.grad_kind_combox.currentIndexChanged.connect(self.GradFuncandAttr)
                        self.grad_child_window.grad_dx_spinbox.valueChanged.connect(self.GradFuncandAttr)
                        self.grad_child_window.grad_dy_spinbox.valueChanged.connect(self.GradFuncandAttr)
                except:
                    pass
            elif item.text() == "阈值处理":
                #更新图片
                self.img = self.process_img
                #保存操作之前的图片
                self.tmp = self.img
                self.dictAssign()
                pyttsx3.speak("阈值处理")
                try:
                    self.threshold_child_window.show()
                    self.child_window_list.append('threshold')
                    if self.threshold_child_window.isVisible():
                        self.ThresholdFuncandAttr()
                        self.threshold_child_window.threshold_kind_combox.currentIndexChanged.connect(self.ThresholdFuncandAttr)
                        self.threshold_child_window.threshold_thresh_spinbox.valueChanged.connect(self.ThresholdFuncandAttr)
                        self.threshold_child_window.threshold_maxval_spinbox.valueChanged.connect(self.ThresholdFuncandAttr)
                except:
                    pass
            elif item.text() == "边缘检测":
                #更新图片
                self.img = self.process_img
                #保存操作之前的图片
                self.tmp = self.img
                self.dictAssign()
                pyttsx3.speak("边缘检测")
                try:
                    self.edge_child_window.show()
                    self.child_window_list.append('edge')
                    if self.edge_child_window.isVisible():
                        self.EdgeFuncandAttr()
                        self.edge_child_window.edge_threshold1_spinbox.valueChanged.connect(self.EdgeFuncandAttr)
                        self.edge_child_window.edge_threshold2_spinbox.valueChanged.connect(self.EdgeFuncandAttr)
                except:
                    pass
            elif item.text() == "轮廓检测":
                #更新图片
                self.img = self.process_img
                #保存操作之前的图片
                self.tmp = self.img
                self.dictAssign()
                pyttsx3.speak("轮廓检测")
                try:
                    self.contour_child_window.show()
                    self.child_window_list.append('contour')
                    if self.contour_child_window.isVisible():
                        self.ContourFuncandAttr()
                        self.contour_child_window.contour_method_combobox.currentIndexChanged.connect(self.ContourFuncandAttr)
                        self.contour_child_window.contour_mode_combobox.currentIndexChanged.connect(self.ContourFuncandAttr)
                except:
                    pass
            elif item.text() == "均衡化":
                #更新图片
                self.img = self.process_img
                #保存操作之前的图片
                self.tmp = self.img
                self.dictAssign()
                pyttsx3.speak("均衡化")
                try:
                    self.equalize_child_window.show()
                    self.child_window_list.append('equalize')
                    if self.equalize_child_window.isVisible():
                        self.EqualizeFuncandAttr()
                        self.equalize_child_window.equalize_blue_checkBox.stateChanged.connect(self.EqualizeFuncandAttr)
                        self.equalize_child_window.equalize_green_checkBox.stateChanged.connect(self.EqualizeFuncandAttr)
                        self.equalize_child_window.equalize_red_checkBox.stateChanged.connect(self.EqualizeFuncandAttr)
                except:
                    pass
            elif item.text() == "直线检测":
                #更新图片
                self.img = self.process_img
                #保存操作之前的图片
                self.tmp = self.img
                self.dictAssign()
                pyttsx3.speak("直线检测")
                try:
                    self.houghLine_child_window.show()
                    self.child_window_list.append('houghLine')
                    if self.houghLine_child_window.isVisible():
                        self.HoughLineFuncandAttr()
                        self.houghLine_child_window.houghline_max_gap_spinbox.valueChanged.connect(self.HoughLineFuncandAttr)
                        self.houghLine_child_window.houghline_min_length_spinbox.valueChanged.connect(self.HoughLineFuncandAttr)
                        self.houghLine_child_window.houghline_thresh_spinbox.valueChanged.connect(self.HoughLineFuncandAttr)
                except:
                    pass
            elif item.text() == "亮度调节":
                #更新图片
                self.img = self.process_img
                #保存操作之前的图片
                self.tmp = self.img
                self.dictAssign()
                pyttsx3.speak("亮度调节")
                try:
                    self.light_child_window.show()
                    self.child_window_list.append('light')
                    if self.light_child_window.isVisible():
                        self.LightFuncandAttr()
                        self.light_child_window.light_alpha_spinbox.valueChanged.connect(self.LightFuncandAttr)
                        self.light_child_window.light_beta_spinbox.valueChanged.connect(self.LightFuncandAttr)
                except:
                    pass
            elif item.text() == "伽马校正":
                #更新图片
                self.img = self.process_img
                #保存操作之前的图片
                self.tmp = self.img
                self.dictAssign()
                pyttsx3.speak("伽马校正")
                try:
                    self.gamma_child_window.show()
                    self.child_window_list.append('gamma')
                    if self.gamma_child_window.isVisible():
                        self.GammaFuncandAttr()
                        self.gamma_child_window.gamma_spinbox.valueChanged.connect(self.GammaFuncandAttr)
                except:
                    pass
            elif item.text() == "直方图":
                pyttsx3.speak("显示图像直方图")
                try:
                    color = ('b','g','r')
                    if plt.fignum_exists(1):
                        plt.close()
                    histb = cv2.calcHist([self.process_img],[0],None,[256],[0,255])
                    histg = cv2.calcHist([self.process_img],[1],None,[256],[0,255])
                    histr = cv2.calcHist([self.process_img],[2],None,[256],[0,255])
                    plt.plot(range(256),histb,color='b')
                    plt.plot(range(256),histg,color='g')
                    plt.plot(range(256),histr,color='r')
                    plt.xlim([0,256])
                    plt.show()
                except:
                    pass

                
    
    '''处理属性'''
    #平滑处理
    def FilterFuncandAttr(self):
        try:
            filter_kind = self.fliter_child_window.fliter_kind_combox.currentText()
            filter_ksize = self.fliter_child_window.fliter_ksize_spinbox.value()
            filter_sigmax = 0

            img_copy = self.img.copy()
            if filter_kind == "均值滤波":
                self.process_img = cv2.blur(img_copy,(filter_ksize,filter_ksize))
            elif filter_kind == "高斯滤波":
                self.process_img = cv2.GaussianBlur(img_copy,(filter_ksize,filter_ksize),filter_sigmax)
            elif filter_kind == "中值滤波":
                self.process_img = cv2.medianBlur(img_copy,filter_ksize)
            self.show_img(self.process_img)
        except:
            pass

    #形态学
    def MorphFuncandAttr(self):
        try:
            morph_kind = self.morph_child_window.morph_kind_combox.currentText()
            morph_ksize = self.morph_child_window.morph_ksize_spinbox.value()
            morph_kshape = self.morph_child_window.morph_kshape_combox.currentText()

            if morph_kind == "腐蚀操作":
                morph_kind = cv2.MORPH_ERODE
            elif morph_kind == "膨胀操作":
                morph_kind = cv2.MORPH_DILATE
            elif morph_kind == "开操作":
                morph_kind = cv2.MORPH_OPEN
            elif morph_kind == "闭操作":
                morph_kind = cv2.MORPH_CLOSE
            elif morph_kind == "梯度操作":
                morph_kind = cv2.MORPH_GRADIENT
            elif morph_kind == "顶帽操作":
                morph_kind = cv2.MORPH_TOPHAT
            elif morph_kind == "黑帽操作":
                morph_kind = cv2.MORPH_BLACKHAT
            
            if morph_kshape == "方形":
                morph_kshape = cv2.MORPH_RECT
            if morph_kshape == "十字形":
                morph_kshape = cv2.MORPH_CROSS
            if morph_kshape == "椭圆形":
                morph_kshape = cv2.MORPH_ELLIPSE

            img_copy = self.img.copy()
            morph_kernal = cv2.getStructuringElement(morph_kshape,(morph_ksize,morph_ksize))
            self.process_img = cv2.morphologyEx(img_copy,morph_kind,morph_kernal)
            self.show_img(self.process_img)
        except:
            pass

    #图像梯度
    def GradFuncandAttr(self):
        try:
            grad_kind = self.grad_child_window.grad_kind_combox.currentText()
            #核大小改变了没什么效果
            grad_dx = self.grad_child_window.grad_dx_spinbox.value()
            grad_dy = self.grad_child_window.grad_dy_spinbox.value()

            img_copy = self.img.copy()
            if grad_kind == "Sobel算子":
                self.process_img = cv2.Sobel(img_copy,-1,grad_dx,grad_dy)
            if grad_kind == "Scharr算子":
                self.process_img = cv2.Scharr(img_copy,-1,grad_dx,grad_dy)
            if grad_kind == "Laplacian算子":
                self.process_img = cv2.Laplacian(img_copy,-1)
            self.show_img(self.process_img)
        except:
            pass
    
    #阈值处理
    def ThresholdFuncandAttr(self):
        try:
            threshold_thresh = self.threshold_child_window.threshold_thresh_spinbox.value()
            threshold_maxval = self.threshold_child_window.threshold_maxval_spinbox.value()
            threshold_kind = self.threshold_child_window.threshold_kind_combox.currentText()

            if threshold_kind == "二值化阈值处理":
                threshold_kind = cv2.THRESH_BINARY
            if threshold_kind == "反二值化阈值处理":
                threshold_kind = cv2.THRESH_BINARY_INV
            if threshold_kind == "截断阈值化处理":
                threshold_kind = cv2.THRESH_TRUNC
            if threshold_kind == "超阈值零处理":
                threshold_kind = cv2.THRESH_TOZERO
            if threshold_kind == "低阈值零处理":
                threshold_kind = cv2.THRESH_TOZERO_INV

            img_copy = self.img.copy()
            self.process_img = cv2.cvtColor(img_copy,cv2.COLOR_RGB2GRAY)
            #没有[1]会崩溃
            self.process_img = cv2.threshold(self.process_img,threshold_thresh,threshold_maxval,threshold_kind)[1]
            self.process_img = cv2.cvtColor(self.process_img,cv2.COLOR_GRAY2BGR)
            self.show_img(self.process_img)
        except:
            pass
    
    #边缘检测
    def EdgeFuncandAttr(self):
        try:
            edge_threshold1 = self.edge_child_window.edge_threshold1_spinbox.value()
            edge_threshold2 = self.edge_child_window.edge_threshold2_spinbox.value()

            self.process_img = cv2.Canny(self.img,edge_threshold1,edge_threshold2)
            self.process_img = cv2.cvtColor(self.process_img,cv2.COLOR_GRAY2BGR)
            self.show_img(self.process_img)
        except:
            pass

    #轮廓检测
    def ContourFuncandAttr(self):
        try:
            #检测轮廓层级关系
            contour_mode = self.contour_child_window.contour_mode_combobox.currentText()
            #近似方法
            contour_method = self.contour_child_window.contour_method_combobox.currentText()

            if contour_mode == "外轮廓":
                contour_mode = cv2.RETR_EXTERNAL
            elif contour_mode == "轮廓列表":
                contour_mode = cv2.RETR_LIST
            elif contour_mode == "外轮廓与内孔":
                contour_mode = cv2.RETR_CCOMP
            elif contour_mode == "轮廓等级树":
                contour_mode == cv2.RETR_TREE

            if contour_method == "简易近似":
                contour_method = cv2.CHAIN_APPROX_SIMPLE

            img_copy = self.img.copy()
            img_gray = cv2.cvtColor(img_copy,cv2.COLOR_BGR2GRAY)
            cnts,_ = cv2.findContours(img_gray,contour_mode,contour_method)

            cv2.drawContours(img_copy,cnts,-1,(0,255,0),3)
            self.process_img = img_copy
            self.show_img(self.process_img)
        except:
            pass
    
    #均衡化
    def EqualizeFuncandAttr(self):
        try:
            #不可对原图进行分割通道，否则改变按钮状态后不会发生改变
            img_copy = self.img.copy()
            self.process_img = img_copy
            b,g,r = cv2.split(self.process_img)
            if self.equalize_child_window.equalize_blue_checkBox.isChecked():
                b = cv2.equalizeHist(b)
            if self.equalize_child_window.equalize_green_checkBox.isChecked():
                g = cv2.equalizeHist(g)
            if self.equalize_child_window.equalize_red_checkBox.isChecked():
                r = cv2.equalizeHist(r)
            #这个操作会改变 img_copy 的值
            cv2.merge((b,g,r),self.process_img)
            self.show_img(self.process_img)
        except:
            pass
    
    #直线检测
    def HoughLineFuncandAttr(self):
        try:
            houghline_thresh = self.houghLine_child_window.houghline_thresh_spinbox.value()
            houghline_min_length = self.houghLine_child_window.houghline_min_length_spinbox.value()
            houghline_max_gap = self.houghLine_child_window.houghline_max_gap_spinbox.value()

            img_copy = self.img.copy()
            gray_img = cv2.cvtColor(img_copy,cv2.COLOR_BGR2GRAY)
            edge_img = cv2.Canny(gray_img,50,150,apertureSize=3)
            lines = cv2.HoughLinesP(edge_img,1,np.pi/180,houghline_thresh,houghline_min_length,houghline_max_gap)
            if lines is None: 
                QMessageBox.information(self,"出错啦！","未找到直线！")
            else:
                for line in lines:
                    x1,y1,x2,y2 = line[0]
                    cv2.line(self.process_img,(x1,y1),(x2,y2),(0,0,0),1)
                self.show_img(self.process_img)
        except:
            pass
    
    #亮度调节
    def LightFuncandAttr(self):
        try:
            light_alpha = self.light_child_window.light_alpha_spinbox.value()
            light_beta = self.light_child_window.light_beta_spinbox.value()

            blank = np.zeros(self.img.shape,self.img.dtype)
            img_copy = self.img.copy()
            self.process_img = cv2.addWeighted(img_copy,light_alpha,blank,1 - light_alpha,light_beta)
            self.show_img(self.process_img)
        except:
            pass
    
    #伽马校正
    def GammaFuncandAttr(self):
        try:
            gamma = self.gamma_child_window.gamma_spinbox.value()

            gamma_table = [np.power(x / 255.0,gamma) * 255.0 for x in range(256)]
            gamma_table = np.round(np.array(gamma_table)).astype(np.uint8)
            img_copy = self.img.copy()
            self.process_img = cv2.LUT(img_copy,gamma_table)
            self.show_img(self.process_img)
        except:
            pass
    
    #缩放
    
    #重写closeEvent 主窗口与子窗口一同关闭
    def closeEvent(self, event):
        sys.exit(0)

    #关闭所有子窗口 用于还原
    def closeAllChildWindow(self):
        if self.fliter_child_window.isVisible():
            self.fliter_child_window.close()
        if self.morph_child_window.isVisible():
            self.morph_child_window.close()
        if self.grad_child_window.isVisible():
            self.grad_child_window.close()
        if self.threshold_child_window.isVisible():
            self.threshold_child_window.close()
        if self.edge_child_window.isVisible():
            self.edge_child_window.close()
        if self.contour_child_window.isVisible():
            self.contour_child_window.close()
        if self.equalize_child_window.isVisible():
            self.equalize_child_window.close()
        if self.houghLine_child_window.isVisible():
            self.houghLine_child_window.close()
        if self.light_child_window.isVisible():
            self.light_child_window.close()
        if self.gamma_child_window.isVisible():
            self.gamma_child_window.close()

    #点击时/撤销时关闭上一次操作的子窗口 防止保存文件与显示不符
    def RevocationCloseChildWindow(self):
        if self.child_window_list[self.revocation_index] == 'gray':
            pass
        if self.child_window_list[self.revocation_index] == 'fliter' and self.fliter_child_window.isVisible():
            self.fliter_child_window.close()
        if self.child_window_list[self.revocation_index] == 'morph' and self.morph_child_window.isVisible():
            self.morph_child_window.close()
        if self.child_window_list[self.revocation_index] == 'grad' and self.grad_child_window.isVisible():
            self.grad_child_window.close()
        if self.child_window_list[self.revocation_index] == 'threshold' and self.threshold_child_window.isVisible():
            self.threshold_child_window.close()
        if self.child_window_list[self.revocation_index] == 'edge' and self.edge_child_window.isVisible():
            self.edge_child_window.close()
        if self.child_window_list[self.revocation_index] == 'contour' and self.contour_child_window.isVisible():
            self.contour_child_window.close()
        if self.child_window_list[self.revocation_index] == 'equalize' and self.equalize_child_window.isVisible():
            self.equalize_child_window.close()
        if self.child_window_list[self.revocation_index] == 'houghLine' and self.houghLine_child_window.isVisible():
            self.houghLine_child_window.close()
        if self.child_window_list[self.revocation_index] == 'light' and self.light_child_window.isVisible():
            self.light_child_window.close()
        if self.child_window_list[self.revocation_index] == 'gamma' and self.gamma_child_window.isVisible():
            self.gamma_child_window.close()
        self.child_window_list.pop(self.revocation_index)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    splash = MySplash('AikPS_custom\\kunkun.gif')
    splash.show()
    def showWindow():
        splash.close()
        window.show()
    QApplication.processEvents()
    window = Window()
    QTimer.singleShot(4500,showWindow)
    sys.exit(app.exec())